package maple.util;

import java.util.TreeMap;

import maple.lang.Command;
import maple.lang.Language;

public abstract class Task extends Object
{
	public static enum Property{ SENDER, COMMAND, RECEIVER };
	
	protected boolean _available;
	protected String _sender;
	protected String _command;
	protected String _receiver;
	protected Language.Instruction _instruction;
	protected TreeMap< String, String > _properties;
	protected long _trigger_time;

	/**
	 * construct a new task with the specified sender, command and receiver
	 *
	 * @param	_sender		the specified _sender
	 * @param	_command		the specified _command
	 * @param	_receiver	the specified _receiver
	 *
	 * @author	snowfoxy
	 * @since	2011-11-15
	 */
	public Task( final String sender, final Command command, final String receiver )
	{
		_available = false;
		
		if( command.isAvailable() )
		{
			_sender = sender;
			_command = command.toString();
			_receiver = receiver;
			
			_instruction = command.getInstruction();
			_properties = new TreeMap< String, String >();
			for( String parameter : command.getParameters() )
			{
				_properties.put( parameter, command.getParameter( parameter ) );
			}
			_trigger_time = 0;
			_available = isValid();
		}
	}

	/**
	 * return true if this task contains the specified property or null if this task is not available 
	 *
	 * @param	property	the specified property
	 * @return	true if this task contains the specified property
	 *
	 * @author	snowfoxy
	 * @since	2011-11-15
	 */
	public boolean containsProperty( final String property )
	{
		if( _available )
		{
			return _properties.containsKey( property );
		}
		return false;
	}

	/**
	 * return the _command of this task or null if this task is not available
	 *
	 * @return	the _command of this task 
	 *
	 * @author	snowfoxy
	 * @since	2011-11-15
	 */
	public String getCommand()
	{
		if( _available )
		{
			return _command;
		}
		return null;
	}

	/**
	 * return the values of the specified property in this task or null if this task is not available
	 *
	 * @param	property	the specified property 
	 * @return	the values of the specified property
	 *
	 * @author	snowfoxy
	 * @since	2011-11-15
	 */
	public String getProperty( final String property )
	{
		if( _available )
		{
			return _properties.get( property );
		}
		return null;
	}

	/**
	 * return the _receiver of this task or null if this task is not available
	 *
	 * @return	the _receiver of this task
	 *
	 * @author	snowfoxy
	 * @since	2011-11-15
	 */
	public String getReceiver()
	{
		if( _available )
		{
			return _receiver;
		}
		return null;
	}

	/**
	 * return the _sender of this task or null if this task is not available
	 *
	 * @return	the _sender of this task
	 *
	 * @author	snowfoxy
	 * @since	2011-11-15
	 */
	public String getSender()
	{
		if( _available )
		{
			return _sender;
		}
		return null;
	}

	/**
	 * return the _instruction of this task or null if this task is not available
	 *
	 * @return	the _instruction of this task
	 *
	 * @author	snowfoxy
	 * @since	2011-11-15
	 */
	public Language.Instruction getInstruction()
	{
		if( _available )
		{
			return _instruction;
		}
		return null;
	}

	/**
	 * return the trigger time of this task or -1 if this task is not available
	 *
	 * @return	the trigger time of this task
	 *
	 * @author	snowfoxy
	 * @since	2011-11-15
	 */
	public long getTriggerTime()
	{
		if( _available )
		{
			return _trigger_time;
		}
		return -1;
	}

	/**
	 * return true if this task is available
	 *
	 * @return	true if this task is available
	 *
	 * @author	snowfoxy
	 * @since	2011-11-15
	 */
	public boolean isAvailable()
	{
		return _available;
	}

	/**
	 * return true if this task is valid 
	 *
	 * @return	true if this task is valid 
	 *
	 * @author	snowfoxy
	 * @since	2011-11-15
	 */
	protected boolean isValid()
	{
		if( _sender.equals( "" ) )
		{
			return false;
		}
		else if( _instruction == null )
		{
			return false;
		}
		else if( _receiver.equals( "" ) )
		{
			return false;
		}
		return true;
	}

	/**
	 * associate the specified values with the specified property
	 *
	 * @param	property	the specified property 
	 * @param	value		the values to be associated with the specified property
	 *
	 * @author	snowfoxy
	 * @since	2011-11-15
	 */
	public void setProperty( final String property, final String value )
	{
		if( _available )
		{
			_properties.put( property, value );
		}
	}

	/**
	 * associate the specified value with the trigger time
	 *
	 * @param	_trigger_time	the specified value
	 *
	 * @author	snowfoxy
	 * @since	2011-11-15
	 */
	public void setTriggerTime( final long trigger_time )
	{
		if( _available )
		{
			_trigger_time = trigger_time;
		}
	}

	/**
	 * return the String representation of this task or null if this task is not available
	 *
	 * @return	the String representation of this task
	 *
	 * @author	snowfoxy
	 * @since	2011-11-15
	 */
	public String toString()
	{
		if( _available )
		{
			String task = _receiver
						  + Language.DELIMITER
						  + _instruction
						  + Language.DELIMITER;

			for( String property : _properties.keySet() )
			{
				task = task
					   + Language.DELIMITER
					   + property
					   + Language.ASSIGN
					   + Language.QUOTE
					   + _properties.get( property )
					   + Language.QUOTE;
			}

			task = task + Language.DELIMITER + _sender;
			
			return task;
		}
		return null;
	}
}
